/**
 * Aibton.com Inc.
 * Copyright (c) 2004-2017 All Rights Reserved.
 */
package com.aibton.framework.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aibton.framework.exception.RequestException;
import com.aibton.framework.validate.annotation.Length;
import com.aibton.framework.validate.annotation.NotEmpty;
import com.aibton.framework.validate.annotation.NotNull;

/**
 * Ab框架校验器工具类
 * @author huzhihui
 * @version v 0.1 2017/5/11 22:38 huzhihui Exp $$
 */
public class AibtonValidateUtils {

    private static final Logger LOGGER      = LoggerFactory.getLogger(AibtonValidateUtils.class);

    /**
     * 方法前缀
     */
    private static final String functionPre = "check";

    /**
     * 校验器进行校验
     * 如果校验失败直接抛出异常，ab框架异常处理器自动解析
     * @param bean  校验对象
     */
    public static void validate(Object bean) {
        Class<?> objectClass = bean.getClass();
        // 检测field是否存在
        try {
            // 获取实体字段集合
            Field[] fields = objectClass.getDeclaredFields();
            for (Field f : fields) {
                // 通过反射获取该属性对应的值
                f.setAccessible(true);
                // 获取字段值
                Object value = f.get(bean);
                // 获取字段上的注解集合
                Annotation[] arrayAno = f.getAnnotations();
                for (Annotation annotation : arrayAno) {
                    Object abValidateUtils = AibtonValidateUtils.class.newInstance();
                    // 根据方法名获取该方法
                    Method m = abValidateUtils.getClass().getDeclaredMethod(
                        functionPre + annotation.annotationType().getSimpleName().substring(2),
                        Annotation.class, Object.class, Field.class);
                    m.invoke(abValidateUtils, annotation, value, f);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 检查非NULL
     * @param annotation    注解
     * @param value 值
     * @param field 方法
     */
    @SuppressWarnings("unused")
    private void checkNotNull(Annotation annotation, Object value, Field field) {
        NotNull notNull = (NotNull) annotation;
        if (null == value) {
            LoggerUtils.error(LOGGER, "参数校验失败:{0}  {1}", field.getName(), notNull.message());
            throw new RequestException("参数校验失败:" + field.getName() + " " + notNull.message());
        }
    }

    /**
     * 检查非空
     * @param annotation    注解
     * @param value 值
     * @param field 方法
     */
    @SuppressWarnings({ "unused", "rawtypes" })
    private void checkNotEmpty(Annotation annotation, Object value, Field field) {
        NotEmpty notEmpty = (NotEmpty) annotation;
        if (null == value) {
            LoggerUtils.error(LOGGER, "参数校验失败:{0}  {1}", field.getName(), notEmpty.message());
            throw new RequestException("参数校验失败:" + field.getName() + " " + notEmpty.message());
        } else if (value instanceof String && value.toString().trim().equals("")) {
            LoggerUtils.error(LOGGER, "参数校验失败:{0}  {1}", field.getName(), notEmpty.message());
            throw new RequestException("参数校验失败:" + field.getName() + " " + notEmpty.message());
        } else if (value instanceof List && (((List) value).size() == 0)) {
            LoggerUtils.error(LOGGER, "参数校验失败:{0}  {1}", field.getName(), notEmpty.message());
            throw new RequestException("参数校验失败:" + field.getName() + " " + notEmpty.message());
        } else if (value instanceof Map && (((Map) value).size() == 0)) {
            LoggerUtils.error(LOGGER, "参数校验失败:{0}  {1}", field.getName(), notEmpty.message());
            throw new RequestException("参数校验失败:" + field.getName() + " " + notEmpty.message());
        }
    }

    /**
     * 检查长度
     * @param annotation    注解
     * @param value 值
     * @param field 方法
     */
    @SuppressWarnings("unused")
    private void checkLength(Annotation annotation, Object value, Field field) {
        Length length = (Length) annotation;
        if (null == value || value.toString().length() < length.min()
            || value.toString().length() > length.max()) {
            LoggerUtils.error(LOGGER, "参数校验失败:{0}  {1}", field.getName(), length.message());
            throw new RequestException("参数校验失败:" + field.getName() + " " + length.message());
        }
    }
}
